<?php

namespace WebmanGrpc;

use Webman\Route;
use WebmanGrpc\Client\GrpcClient;
use WebmanGrpc\Transformer\RequestTransformerInterface;
use WebmanGrpc\Transformer\ResponseTransformerInterface;
use Workerman\Protocols\Http\Request;
use Workerman\Protocols\Http\Response;

/**
 * HTTP到gRPC网关
 * 
 * 提供HTTP请求到gRPC请求的转换功能，支持：
 * - 路由配置
 * - 请求/响应转换
 * - 错误处理
 */
class HttpGateway
{
    /**
     * 配置
     */
    protected array $config;
    
    /**
     * 构造函数
     * 
     * @param array $config 配置参数
     */
    public function __construct(array $config = [])
    {
        $this->config = array_merge(Grpc::getConfig('http_gateway', []), $config);
        
        // 注册路由
        $this->registerRoutes();
    }
    
    /**
     * 注册路由
     * 
     * @return void
     */
    protected function registerRoutes(): void
    {
        if (!$this->config['enabled']) {
            return;
        }
        
        $routes = $this->config['routes'] ?? [];
        
        foreach ($routes as $route) {
            $path = $route['path'];
            $method = $route['method'] ?? 'GET';
            $service = $route['service'];
            $serviceMethod = $route['method'];
            $requestTransformer = $route['request_transformer'] ?? null;
            $responseTransformer = $route['response_transformer'] ?? null;
            $address = $route['address'] ?? '127.0.0.1:50051';
            $options = $route['options'] ?? [];
            
            // 注册路由
            Route::add($method, $path, function (Request $httpRequest) use (
                $service,
                $serviceMethod,
                $requestTransformer,
                $responseTransformer,
                $address,
                $options
            ) {
                return $this->handleRequest(
                    $httpRequest,
                    $service,
                    $serviceMethod,
                    $requestTransformer,
                    $responseTransformer,
                    $address,
                    $options
                );
            });
        }
    }
    
    /**
     * 处理请求
     * 
     * @param Request $httpRequest HTTP请求
     * @param string $service 服务名称
     * @param string $serviceMethod 服务方法
     * @param string|null $requestTransformer 请求转换器类名
     * @param string|null $responseTransformer 响应转换器类名
     * @param string $address gRPC服务地址
     * @param array $options 客户端选项
     * @return Response HTTP响应
     */
    protected function handleRequest(
        Request $httpRequest,
        string $service,
        string $serviceMethod,
        ?string $requestTransformer,
        ?string $responseTransformer,
        string $address,
        array $options
    ): Response {
        try {
            // 创建gRPC客户端
            $client = new GrpcClient($address, $options);
            
            // 转换请求
            $grpcRequest = $this->transformRequest($httpRequest, $requestTransformer);
            
            // 调用gRPC服务
            $grpcResponse = $client->call($service, $serviceMethod, $grpcRequest);
            
            // 转换响应
            $httpResponse = $this->transformResponse($grpcResponse, $responseTransformer);
            
            return $httpResponse;
        } catch (\Throwable $e) {
            // 处理错误
            return $this->handleError($e);
        }
    }
    
    /**
     * 转换请求
     * 
     * @param Request $httpRequest HTTP请求
     * @param string|null $transformerClass 转换器类名
     * @return \Google\Protobuf\Internal\Message gRPC请求
     */
    protected function transformRequest(Request $httpRequest, ?string $transformerClass): \Google\Protobuf\Internal\Message
    {
        if ($transformerClass && class_exists($transformerClass)) {
            $transformer = new $transformerClass();
            
            if ($transformer instanceof RequestTransformerInterface) {
                return $transformer->transform($httpRequest);
            }
        }
        
        // 默认转换逻辑
        return $this->defaultRequestTransform($httpRequest);
    }
    
    /**
     * 转换响应
     * 
     * @param \Google\Protobuf\Internal\Message $grpcResponse gRPC响应
     * @param string|null $transformerClass 转换器类名
     * @return Response HTTP响应
     */
    protected function transformResponse(\Google\Protobuf\Internal\Message $grpcResponse, ?string $transformerClass): Response
    {
        if ($transformerClass && class_exists($transformerClass)) {
            $transformer = new $transformerClass();
            
            if ($transformer instanceof ResponseTransformerInterface) {
                return $transformer->transform($grpcResponse);
            }
        }
        
        // 默认转换逻辑
        return $this->defaultResponseTransform($grpcResponse);
    }
    
    /**
     * 默认请求转换
     * 
     * @param Request $httpRequest HTTP请求
     * @return \Google\Protobuf\Internal\Message gRPC请求
     */
    protected function defaultRequestTransform(Request $httpRequest): \Google\Protobuf\Internal\Message
    {
        // 这里应该根据实际的服务方法返回对应的请求消息
        // 由于没有具体的服务信息，这里只是一个示例
        
        // 获取请求体
        $body = $httpRequest->rawBody();
        $data = json_decode($body, true);
        
        // 创建一个通用的请求消息（实际使用时应该替换为具体的消息类）
        $request = new class extends \Google\Protobuf\Internal\Message {
            // 这里应该有具体的字段定义
        };
        
        // 设置请求字段（实际使用时应该根据具体的消息类设置）
        // $request->setField($data['field'] ?? null);
        
        return $request;
    }
    
    /**
     * 默认响应转换
     * 
     * @param \Google\Protobuf\Internal\Message $grpcResponse gRPC响应
     * @return Response HTTP响应
     */
    protected function defaultResponseTransform(\Google\Protobuf\Internal\Message $grpcResponse): Response
    {
        // 将gRPC响应转换为JSON
        $data = [];
        
        // 获取响应字段（实际使用时应该根据具体的消息类获取）
        // $data['field'] = $grpcResponse->getField();
        
        return json($data);
    }
    
    /**
     * 处理错误
     * 
     * @param \Throwable $e 异常
     * @return Response HTTP响应
     */
    protected function handleError(\Throwable $e): Response
    {
        // 记录错误日志
        echo "HTTP to gRPC gateway error: " . $e->getMessage() . "\n";
        
        // 返回错误响应
        return json([
            'error' => $e->getMessage(),
            'code' => 500,
        ], 500);
    }
}